package com.cskaoyan.javase.oop3._3local._4life;

/**
 * 为什么局部内部类访问局部变量,该局部变量就必须是常量?
 *      1.首先要考虑的是对象和方法内局部变量的生命周期的冲突
 *      方法出栈后,局部变量随之销毁
 *      但是对象却不会,如果对象中的方法需要访问局部变量,但这时局部变量已经不存在了,这就是生命周期的冲突
 *
 *      为了解决这个生命周期的冲突,创建局部内部类对象时,JVM会自动将对象的成员方法中需要访问的局部变量,作为对象的成员变量.
 *      这时,即便方法出栈,仍然能够正常访问该局部变量
 *
 *      2.以上解决了生命周期的问题,但解决问题的方案,可能本身就是一个问题,又会引入新的问题.
 *      如果允许在局部内部类当中修改该局部变量的取值,那么:
 *          代码上看起来修改的是局部变量的取值
 *          但从内存上来看修改的是自身的成员变量
 *          于是就存在"同步取值"的问题
 *          于是还需要费尽心思同步取值
 *          但这个同步的解决方案也许还会引入新的问题
 *
 *   所以最终Java的设计者,决定不允许修改取值,将局部变量作为一个常量,既然不可修改,那就没有同步问题.
 *
 *   补充:
 *   在Java7和之前的版本中,这个局部变量必须显式的声明为final,否者会编译报错
 *   但是Java8以后,编译器会在编译代码时,在底层加上final,程序员不需要自己加final
 *
 * @since 14:51
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        EnclosedClazz ec = new EnclosedClazz();
        IA ia = ec.test();
        ia.testInner();
    }
}

class EnclosedClazz {
    public IA test() {
        // 定义局部变量
        int a = 10;
        // 定义局部内部类
        class IAImpl implements IA {
            // 局部内部类的成员方法
            @Override
            public void testInner() {
                System.out.println(a);
            }
        }
        IAImpl ia = new IAImpl();
        ia.testInner();
        System.out.println(a);
        return ia;
    }
}

interface IA {
    void testInner();
}